/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 * Mozilla.org.
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Author(s): Michael Ryabushkin
 *
 * ***** END LICENSE BLOCK ***** */

/*----------------------
 Contains some of the code is from Mozilla original Cookie Editor
 ----------------------*/


/*##################################################################################### */

//interface variables
var cookiemanager = null;
var gDateService = null;

//cookies list
var cookies = [];

var cookieBundle;
var cookiesTree;
const nsICookie = Components.interfaces.nsICookie;

var lastCookieSortColumn = "";
var lastCookieSortAscending = false;

var lastsearchNameKey = "addneditcookies.lastsearch.name";
var lastsearchHostKey = "addneditcookies.lastsearch.host";

var	supress_getCellText = false

var cookiesTreeView = {
		rowCount : 0,
		setTree : function(tree){},
		getImageSrc : function(row,column) {},
		getProgressMode : function(row,column) {},
		getCellValue : function(row,column) {},
		getCellText : function(row,column){
			if ( supress_getCellText )
				return "";
			var rv="";	
			if ((column=="domainCol")|(column.id=="domainCol")) {
				rv = cookies[row].rawHost;
			} else if ((column=="nameCol")|(column.id=="nameCol")) {
				rv = cookies[row].name;
			}
			return rv;
		},
		isSeparator : function(index) {return false;},
		isSorted: function() { return false; },
		isContainer : function(index) {return false;},
		cycleHeader : function(aColId, aElt) {},
		getRowProperties : function(row,column,prop){},
		getColumnProperties : function(column,columnElement,prop){},
		getCellProperties : function(row,prop){}
};

var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService).getBranch("");

var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);


/*##################################################################################### */

/*=============================================================================*/
function Startup()
{

	// intialize gDateService
	cookiemanager = Components.classes["@mozilla.org/cookiemanager;1"].getService();
	cookiemanager = cookiemanager.QueryInterface(Components.interfaces.nsICookieManager);
	if( !gDateService )
	{
		const nsScriptableDateFormat_CONTRACTID = "@mozilla.org/intl/scriptabledateformat;1";
		const nsIScriptableDateFormat = Components.interfaces.nsIScriptableDateFormat;
		gDateService = Components.classes[nsScriptableDateFormat_CONTRACTID]
		.getService(nsIScriptableDateFormat);
	}

	var lastsearchHost = '';
	var lastsearchName = '';

	//check whether we have the host branch
	var aCount = {value:0};
	var childArray = prefs.getChildList(lastsearchHostKey, aCount);
	if( aCount.value == 0 )
		prefs.setCharPref(lastsearchHostKey, '');
	else
		lastsearchHost = prefs.getCharPref(lastsearchHostKey) || '';

	//check whether we have the name branch
	aCount.value = 0;
	childArray = prefs.getChildList(lastsearchNameKey, aCount);
	if( aCount.value == 0 )
		prefs.setCharPref(lastsearchNameKey, '');
	else
		lastsearchName = prefs.getCharPref(lastsearchNameKey) || '';

	document.getElementById('lookupcriterium').value = lastsearchHost;
	loadCookies( lastsearchHost );

	// select the last selected cookie
	for( var i=0; i<cookies.length; i++ )
	{
		if( cookies[i].name == lastsearchName )
		{
			cookiesTree.treeBoxObject.view.selection.select( i );
			break;
		}
	}

}
/*=============================================================================*/

/*=============================================================================*/
function DoLookup(e)
{
	if( e && e.keyCode == 13 || !e )
	{
		var searchfor = document.getElementById('lookupcriterium').value;
		prefs.setCharPref(lastsearchHostKey, searchfor );
		var oldCount = cookiesTreeView.rowCount;
		cookiesTreeView.rowCount = 0;
		cookiesTree.treeBoxObject.rowCountChanged(0, -oldCount);
		cookies = [];
		loadCookies(searchfor);
	}
}
/*=============================================================================*/

/*** @@@@@@@@@@@@@@@@@@@ COOKIES CODE @@@@@@@@@@@@@@@@@@@ ***/

/*==============================================================*/
function Cookie(number,name,value,isDomain,host,rawHost,path,isSecure,expires,
		status,policy) {

	this.number = number;
	this.name = name;
	this.value = value;
	this.isDomain = isDomain;
	this.host = host;
	this.rawHost = rawHost;
	this.path = path;
	this.isSecure = isSecure;
	this.expires = expires;
	this.status = status;
	this.policy = policy;
}
/*==============================================================*/

/*========================================================================*/
function loadCookies(criterium, noresort) {
	if (!cookieBundle)
		cookieBundle = document.getElementById("cookieBundle");

	if (!cookiesTree)
		cookiesTree = document.getElementById("cookiesTree");

	// load cookies into a table
	var enumerator = cookiemanager.enumerator;
	var count = 0;
	while (enumerator.hasMoreElements()) 
	{
		var nextCookie = enumerator.getNext();
		if (!nextCookie) break;
		nextCookie = nextCookie.QueryInterface(Components.interfaces.nsICookie);
		var host = nextCookie.host;
		if (criterium && host.indexOf(criterium) == -1 ) continue;
		if (nextCookie.policy != nsICookie.POLICY_UNKNOWN)
			showPolicyField = true;

		cookies[count] =
			new Cookie(count++, nextCookie.name, nextCookie.value, nextCookie.isDomain, host,
					(host.charAt(0)==".") ? host.substring(1,host.length) : host,
							nextCookie.path, nextCookie.isSecure, nextCookie.expires,
							nextCookie.status, nextCookie.policy);
	}

	cookiesTreeView.rowCount = cookies.length;
	cookiesTree.treeBoxObject.view = cookiesTreeView;

	// sort by host column
	// we need this magic to disable the switching between asc and desc search during lookup
	// it's simple: if lastCookieSortAscending is not equal column - do asc sort always
	var savelastCookieSortAscending = lastCookieSortAscending;
	lastCookieSortAscending = '';
	CookieColumnSort('rawHost', true);
	lastCookieSortAscending = savelastCookieSortAscending; 
}
/*========================================================================*/

/*====================================*/ 
function GetExpiresString(expires) { 
	if (expires) { 
		var date = new Date(1000*expires); 

		if( (navigator.platform.indexOf("Win") == 0) || (navigator.platform.indexOf("Mac") != -1) )  
		{ 
			return gDateService.FormatDateTime("", gDateService.dateFormatLong, 
					gDateService.timeFormatSeconds, date.getFullYear(), 
					date.getMonth()+1, date.getDate(), date.getHours(), 
					date.getMinutes(), date.getSeconds()); 

		} else{ 
			// HACK We are probably on Linux and want a string in long format. 
			// dateService.dateFormatLong on Linux returns a short string, so build our own 
			// this is hint is from penzilla project 
			return twochar(date.getMonth()+1) + '/' + twochar(date.getDate()) + '/' +  date.getFullYear() + ' '  
			+ twochar(date.getHours()) + ':' + twochar(date.getMinutes()) + ':' + twochar(date.getSeconds()); 
		} 

	} 
	return cookieBundle.getString("AtEndOfSession"); 
} 

/*----------------------*/ 
function twochar(s) { 
	var str =   '00' + s;   
	return str.substring( ((str.length)-2) ,str.length); 
} 
/*----------------------*/ 


/*====================================*/ 

/*=============================================================*/
function GetPolicyString(policy) {

	switch (policy) {
	case nsICookie.POLICY_NONE:
		return cookieBundle.getString("policyUnstated");
	case nsICookie.POLICY_NO_CONSENT:
		return cookieBundle.getString("policyNoConsent");
	case nsICookie.POLICY_IMPLICIT_CONSENT:
		return cookieBundle.getString("policyImplicitConsent");
	case nsICookie.POLICY_EXPLICIT_CONSENT:
		return cookieBundle.getString("policyExplicitConsent");
	case nsICookie.POLICY_NO_II:
		return cookieBundle.getString("policyNoIICollected");
	}

	return "";

}
/*=============================================================*/

/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
function CookieSelected() 
{

	var selections = GetTreeSelections(cookiesTree);

	if( !selections.length )
	{
		ClearCookieProperties();
		UI_EnableCookieBtns(false, false);
		return true;
	}


	var idx = selections[0];
	if( idx >= cookies.length )
	{
		// Something got out of synch.  See bug 119812 for details
		dump("Tree and viewer state are out of sync! " +
		"Help us figure out the problem in bug 119812");
		UI_EnableCookieBtns(false, false);
		return false;
	}


	// save last selected name
	prefs.setCharPref( lastsearchNameKey, cookies[idx].name );

	var props = [
	             {id: "ifl_name", value: cookies[idx].name},
	             {id: "ifl_value", value: cookies[idx].value}, 
	             {id: "ifl_isDomain",
	            	 value: cookies[idx].isDomain ?
	            			 cookieBundle.getString("domainColon") : cookieBundle.getString("hostColon")},
	            			 {id: "ifl_host", value: cookies[idx].host},
	            			 {id: "ifl_path", value: cookies[idx].path},
	            			 {id: "ifl_isSecure",
	            				 value: cookies[idx].isSecure ?
	            						 cookieBundle.getString("forSecureOnly") : 
	            							 cookieBundle.getString("forAnyConnection")},
	            							 {id: "ifl_expires", value: GetExpiresString(cookies[idx].expires)},
	            							 {id: "ifl_expiresOrig", value: cookies[idx].expires},
	            							 {id: "ifl_policy", value: GetPolicyString(cookies[idx].policy)}

	            							 ];


	var value;
	var field;
	for( var i = 0; i < props.length; i++ )
	{
		field = document.getElementById(props[i].id);
		if( (selections.length > 1) && (props[i].id != "ifl_isDomain") )
		{
			value = ""; // clear field if multiple selections
		} else {
			value = props[i].value;
		}

		field.value = value;
	}

	// make the delete button active
	UI_EnableCookieBtns(true, ((selections.length >1) ? false : true));

	out_d("Cookie Manager::CookieSelected::END");

	return true;
}
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/

/*============================================*/
function ClearCookieProperties() {
	var properties = 
		["ifl_name","ifl_value","ifl_host","ifl_path","ifl_isSecure",
		 "ifl_expires","ifl_expiresOrig","ifl_policy"];
	for (var prop=0; prop<properties.length; prop++) {
		document.getElementById(properties[prop]).value = "";
	}
}
/*============================================*/

/*=====================================================*/
function CookieColumnSort(column, updateview)
{
	lastCookieSortAscending = SortTree( cookiesTree, cookiesTreeView, cookies,
			column, lastCookieSortColumn, lastCookieSortAscending, updateview );

	lastCookieSortColumn = column;
}
/*=====================================================*/


/*=============================================*/
function UI_EnableCookieBtns(flag, flag2)
{
	document.getElementById('deleteCookie').disabled = !flag;
	document.getElementById('editCookie').disabled = !flag2;

}
/*=============================================*/

//--------------------------------------------------------------
function DeleteCookies() {
	var deletedCookies       = [];

	DeleteSelectedItemFromTree(cookiesTree, cookiesTreeView,
			cookies, deletedCookies);
	if (!cookies.length) {
		ClearCookieProperties();
	}
	FinalizeCookieDeletions( deletedCookies );
}
//--------------------------------------------------------------

//-----------------------------------
function zzzold_DeleteSelectedItemFromTree  (tree, view, table, deletedTable) {

	// Turn off tree selection notifications during the deletion
	tree.treeBoxObject.view.selection.selectEventsSuppressed = true;

	// remove selected items from list (by setting them to null) and place in deleted list
	var selections = GetTreeSelections(tree);
	for (var s=selections.length-1; s>= 0; s--) {
		var i = selections[s];
		//var confirmDeleteMsg = 'Are you sure you want to delete the \'' + cookies[i].name + ' @ ' + cookies[i].host + '\' cookie?' +'\n\n(*You can turn this warning off in Options*)';
		var confirmDeleteMsg = cookieBundle.getString("warningConfirmToDeleteCookie").replace('cookie_name',cookies[i].name + ' @ ' + cookies[i].host);

		if ( (!DeleteConfirmation()) || (confirm( confirmDeleteMsg )) )
		{
			deletedTable[deletedTable.length] = table[i];
			table[i] = null;
		}
	}

	// collapse list by removing all the null entries
	for (var j=0; j<table.length; j++) {
		if (table[j] == null) {
			var k = j;
			while ((k < table.length) && (table[k] == null)) {
				k++;
			}
			table.splice(j, k-j);
			view.rowCount -= k - j;
			tree.treeBoxObject.rowCountChanged(j, j - k);
		}
	}

	// update selection and/or buttons
	if (table.length) {

		// update selection
		var nextSelection = (selections[0] < table.length) ? selections[0] : table.length-1;
		tree.treeBoxObject.view.selection.select(nextSelection);
		tree.treeBoxObject.ensureRowIsVisible(nextSelection);

	} else {

		// disable buttons
		document.getElementById('deleteCookie').setAttribute("disabled", "true")

	}

	tree.treeBoxObject.view.selection.selectEventsSuppressed = false;
}
//---------------------------



//-----------------------------------
function DeleteSelectedItemFromTree  (tree, view, table, deletedTable) {

	var DeleteAll = false;
	var uChoice;
	var prefDeleteConf = GetBoolPrefValue(delconf, true);

	var promptDelete_window_title 		= cookieBundle.getString("promptDelete.window.title");
	var promptDelete_label_warning 			= cookieBundle.getString("promptDelete.label.warning")
	var promptDelete_label_options 			= cookieBundle.getString("promptDelete.label.options")

	var promptDelete_button_Delete = cookieBundle.getString("promptDelete.button.Delete");
	var promptDelete_button_DoNotDelete = cookieBundle.getString("promptDelete.button.DoNotDelete");

	var promptDelete_button_DeleteAll = cookieBundle.getString("promptDelete.button.DeleteAll");
	var promptDelete_button_Cancel = cookieBundle.getString("promptDelete.button.Cancel");


	const eIconClasses = new Array("question-icon", "alert-icon", "message-icon");


	// Turn off tree selection notifications during the deletion
	tree.treeBoxObject.view.selection.selectEventsSuppressed = true;

	// remove selected items from list (by setting them to null) and place in deleted list
	var selections = GetTreeSelections(tree, cookies);

	for (var s=selections.length-1; s>= 0; s--) 
	{
		var i = selections[s];

		// delete = 3, delete all = 0, do not delete = 2, cancel = 1 (promptDelete)

		if ( prefDeleteConf && (!DeleteAll) )
			uChoice = promptDelete ( promptDelete_window_title, 
					eIconClasses[1], 
					promptDelete_label_options, 
					promptDelete_label_warning.replace('cookie_name',cookies[i].name + ' @ ' + cookies[i].host), 
					promptDelete_button_DeleteAll, 
					promptDelete_button_Cancel, 
					promptDelete_button_DoNotDelete , 
					promptDelete_button_Delete, 
					3);

		if (uChoice == 1) 
			s = -1;       //Cancel so s = -1 --> quiting for loop
		else if (uChoice == 0) 
			DeleteAll = true;

		if ( DeleteAll || !prefDeleteConf || (uChoice == 3) )
		{
			supress_getCellText = true;

			deletedTable[deletedTable.length] = table[i];
			table[i] = null;

//			deletedTable[deletedTable.length] = table_temp[i];
//			table_temp[i] = null;

		}

	}


	// collapse list by removing all the null entries
	for (var j=0; j<table.length; j++) {
		if (table[j] == null) {
			var k = j;
			while ((k < table.length) && (table[k] == null)) {
				k++;
			}
			table.splice(j, k-j);
			view.rowCount -= k - j;
			tree.treeBoxObject.rowCountChanged(j, j - k);
		}
	}


	supress_getCellText = false;

	// update selection and/or buttons
	if (table.length) {
		// update selection
		var nextSelection = (selections[0] < table.length) ? selections[0] : table.length-1;
		tree.treeBoxObject.view.selection.select(nextSelection);
		tree.treeBoxObject.ensureRowIsVisible(nextSelection);

	} else {

		// disable buttons
		document.getElementById('deleteCookie').setAttribute("disabled", "true")

	}

	tree.treeBoxObject.view.selection.selectEventsSuppressed = false;
}
//---------------------------

//-----------------------------------
function FinalizeCookieDeletions(deletedCookies) {

	for (var c=0; c<deletedCookies.length; c++) {
		cookiemanager.remove(deletedCookies[c].host,
				deletedCookies[c].name,
				deletedCookies[c].path,
				false); // false -> not blacklist cookie
	}
	deletedCookies.length = 0;

}
//-----------------------------------


/*=================================*/

/*========================*/
function EditCookie()
{
	window.openDialog("editCookie.xul", "_blank", "chrome,width=550,height=350,resizable=yes,modal=yes", "EditCookie");
}
/*========================*/

/*========================*/
function AddCookie()
{
	window.openDialog("editCookie.xul?addcookie", "_blank", "chrome,width=550,height=350,resizable=yes,modal=yes", "EditCookie");
}
/*========================*/
function OpenTextDialog()
{
	window.openDialog("textCookie.xul", "_blank", "chrome,width=550,height=350,resizable=yes,modal=yes", "TextCookie");
}
/*=======================*/
/*
 * Function to load from text (copy&paste)
 */
function LoadText()
{
	//var wod = window.opener.document;
	var txtValue = document.getElementById("cookieTxt").value;
	//window.close();
	SendValues(txtValue);
	document.getElementById("cookieTxt").value = "";
}
/*========================*/
/*
 * Function to load from file for firefox 3 --> geck 1.9.*
 */
function LoadFile()
{
	const nsIFilePicker = Components.interfaces.nsIFilePicker;
	var fp = Components.classes["@mozilla.org/filepicker;1"]
	.createInstance(nsIFilePicker);
	fp.init(window, "Dialog Title", nsIFilePicker.modeOpen);
	fp.appendFilters(nsIFilePicker.filterText);

	var rv = fp.show();

	if (rv == nsIFilePicker.returnOK) {
		var file = fp.file;
		// Get the path as string. Note that you usually won't 
		// need to work with the string paths.
		var path = fp.file.path;
		// work with returned nsILocalFile...

		// open an input stream from file  
		var data = "";  
		var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].  
		createInstance(Components.interfaces.nsIFileInputStream);  
		var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].  
		createInstance(Components.interfaces.nsIConverterInputStream);  
		fstream.init(fp.file, -1, 0, 0);  
		cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish  

		var str = {};   
		var read = 0;  
		do {   
			read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value  
			data += str.value;  
		} while (read != 0);  

		cstream.close(); // this closes fstream  
		SendValues(data);
	}
}
/*========================*/
/*
 * Funtion to send values to cookie Editor window
 */
function SendValues(cookieStr)
{
	// copy data into other string variable to work with
	var fileStr = cookieStr;
	var domainFlag = false;
	var cNameCont = false;
	var cookieName = "";
	var cookieContent = "";
	var cookieHost = "";
	var cookiePath = "/";
	// create an array of each line from the string
	var strLines = fileStr.split("\n");

	for(var i=0; i<strLines.length; i++)
	{
		if( (strLines[i].indexOf("domain") != -1) && (!domainFlag) )
		{
			var domArr = strLines[i].split(": ");
			cookieHost = "."+domArr[1];
			domainFlag = true;
		}
		if(strLines[i].indexOf("=") != -1) // checks if the line has "=" char to set the variable and contents
		{
			var newStr = strLines[i].split("=",2);
			cookieName = newStr[0];
			cookieContTmp = newStr[1].split(";");
			cookieContent = cookieContTmp[0];
			cNameCont = true;
		} 
		if(cNameCont && domainFlag)
		{
			// creates url to the new window
			var xulUrl = "editCookie.xul?addvalues&cn="+cookieName+"&cc="+cookieContent+"&ch="+cookieHost+"&cp="+cookiePath;
			window.openDialog(xulUrl, "_blank", "chrome,width=550,height=350,resizable=yes,modal=yes", "EditCookie");
			cNameCont = false;
		}
	}
}
/* My function to load from file for gecko 5+ --> Firefox 5 and above */
/*
function LoadFile()
{
	Components.utils.import("resource://gre/modules/NetUtil.jsm");  

	const nsIFilePicker = Components.interfaces.nsIFilePicker;
	var fp = Components.classes["@mozilla.org/filepicker;1"]
	.createInstance(nsIFilePicker);
	fp.init(window, "Dialog Title", nsIFilePicker.modeOpen);
	fp.appendFilters(nsIFilePicker.filterText);

	var rv = fp.show();

	if (rv == nsIFilePicker.returnOK) {
		var file = fp.file;
		// Get the path as string. Note that you usually won't 
		// need to work with the string paths.
		//var path = fp.file.path;
		// work with returned nsILocalFile...
		NetUtil.asyncFetch(file, function(inputStream, status) {  
			if (!Components.isSuccessCode(status)) {  
				// Handle error!  
				return;  
			}  
			// The file data is contained within inputStream.  
			// You can read it into a string with  
			var data = NetUtil.readInputStreamToString(inputStream, inputStream.available());  

			var fileStr = data;
			var cookieName;
			var cookieContent;
			var cookieHost = ".facebook.com";
			var cookiePath = "/";

			var strLines = fileStr.split("\n");

			for(var i=0; i<strLines.length; i++)
			{
				if(strLines[i].indexOf("=")!=-1)
				{
					var newStr = strLines[i].split("=",2);
					cookieName = newStr[0];
					cookieContTmp = newStr[1].split(";");
					cookieContent = cookieContTmp[0];

					var xulUrl = "editCookie.xul?addvalues&cn="+cookieName+"&cc="+cookieContent+"&ch="+cookieHost+"&cp="+cookiePath;
					window.openDialog(xulUrl, "_blank", "chrome,width=550,height=350,resizable=yes,modal=yes", "EditCookie");
				}
			}
		});  
	}
}
 */
//--------------------------------
function SelectAllShown() 
{ 
	cookiesTree.treeBoxObject.view.selection.selectAll(); 
	cookiesTree.focus();
}
//--------------------------------

//--------------------------------
function InvertSelection() 
{ 
	var sel = cookiesTree.treeBoxObject.view.selection; 
	var cnt = cookiesTree.treeBoxObject.view.rowCount ;


	for (var i=0;i<cnt;i++)
		sel.toggleSelect(i);

	cookiesTree.focus();

}
//--------------------------------

/*========================*/
function OpenOptions()
{
	window.openDialog("Options.xul", "_blank", "chrome,resizable=yes,modal=yes", "Options");
}
/*========================*/

//---------------------------------------
//this shoudl probably be in libIUtils.js or some other
function cloneObject(what) {

	var temp = new Array();

	for (i in what) {
		temp[i] = what[i];
	}

	return temp;

}
//---------------------------------------